
/*

Design Pattern Automation Toolkit.
Application to create applications with emphasis on Design patterns.
And support for round trip engineering.
Copyright (C) 2004 Vineeth Neelakant. nvineeth@gmail.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
using System;using BusinessLayer;using InfoClasses;using dpatoolkit.UILayer;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using DesignPatternDefinitions;
using System.Data;
using System.IO;
namespace dpatoolkit.UILayer
{
		/// <summary>
		/// Summary description for ReverseEnggPluginForm.
		/// </summary>
		public class ReverseEnggPluginForm : System.Windows.Forms.Form
		{
		private System.Data.DataSet revEnggDataSet;
		private System.Windows.Forms.GroupBox groupBox2;
		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.ListBox plugInListBox;
		private System.Windows.Forms.Button remPluginButton;
		private System.Data.DataColumn dataColumn1;
		private System.Windows.Forms.Button addPluginButton;
		private System.Windows.Forms.DataGrid dataGrid1;
		private System.Data.DataTable ReverseEngineeringPlugins;
		private System.Windows.Forms.Button okButton;
			/// <summary>
			/// Required designer variable.
			/// </summary>
			private System.ComponentModel.Container components = null;
			private static string PluginTable = "ReverseEngineeringPlugins";
			private ArrayList revEngineers = new ArrayList();
			private bool silent=false;
			private static int PathIndex=0;

			public ReverseEnggPluginForm()
			{
				//
				// Required for Windows Form Designer support
				//
				InitializeComponent();
				//this.Paint+=new PaintEventHandler(FormPainter.Paint);
				this.LoadSnapIns();

			
			}

			/// <summary>
			/// Clean up any resources being used.
			/// </summary>
			protected override void Dispose( bool disposing )
			{
				if( disposing )
				{
					if(components != null)
					{
						components.Dispose();
					}
				}
				base.Dispose( disposing );
			}

			#region Windows Form Designer generated code
			/// <summary>
			/// Required method for Designer support - do not modify
			/// the contents of this method with the code editor.
			/// </summary>
			private void InitializeComponent() {
                this.okButton = new System.Windows.Forms.Button();
                this.ReverseEngineeringPlugins = new System.Data.DataTable();
                this.dataColumn1 = new System.Data.DataColumn();
                this.dataGrid1 = new System.Windows.Forms.DataGrid();
                this.addPluginButton = new System.Windows.Forms.Button();
                this.remPluginButton = new System.Windows.Forms.Button();
                this.plugInListBox = new System.Windows.Forms.ListBox();
                this.groupBox1 = new System.Windows.Forms.GroupBox();
                this.groupBox2 = new System.Windows.Forms.GroupBox();
                this.revEnggDataSet = new System.Data.DataSet();
                ((System.ComponentModel.ISupportInitialize)(this.ReverseEngineeringPlugins)).BeginInit();
                ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
                this.groupBox1.SuspendLayout();
                this.groupBox2.SuspendLayout();
                ((System.ComponentModel.ISupportInitialize)(this.revEnggDataSet)).BeginInit();
                this.SuspendLayout();
                // 
                // okButton
                // 
                this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
                this.okButton.Location = new System.Drawing.Point(480, 32);
                this.okButton.Name = "okButton";
                this.okButton.Size = new System.Drawing.Size(75, 23);
                this.okButton.TabIndex = 1;
                this.okButton.Text = "&Ok";
                this.okButton.Click += new System.EventHandler(this.okButton_Click);
                // 
                // ReverseEngineeringPlugins
                // 
                this.ReverseEngineeringPlugins.Columns.AddRange(new System.Data.DataColumn[] {
            this.dataColumn1});
                this.ReverseEngineeringPlugins.Constraints.AddRange(new System.Data.Constraint[] {
            new System.Data.UniqueConstraint("Constraint1", new string[] {
                        "Path"}, true)});
                this.ReverseEngineeringPlugins.PrimaryKey = new System.Data.DataColumn[] {
        this.dataColumn1};
                this.ReverseEngineeringPlugins.TableName = "ReverseEngineeringPlugins";
                // 
                // dataColumn1
                // 
                this.dataColumn1.AllowDBNull = false;
                this.dataColumn1.ColumnName = "Path";
                // 
                // dataGrid1
                // 
                this.dataGrid1.AlternatingBackColor = System.Drawing.Color.Lavender;
                this.dataGrid1.BackColor = System.Drawing.Color.WhiteSmoke;
                this.dataGrid1.BackgroundColor = System.Drawing.Color.LightGray;
                this.dataGrid1.BorderStyle = System.Windows.Forms.BorderStyle.None;
                this.dataGrid1.CaptionBackColor = System.Drawing.Color.LightSteelBlue;
                this.dataGrid1.CaptionForeColor = System.Drawing.Color.MidnightBlue;
                this.dataGrid1.DataMember = "";
                this.dataGrid1.DataSource = this.ReverseEngineeringPlugins;
                this.dataGrid1.FlatMode = true;
                this.dataGrid1.Font = new System.Drawing.Font("Tahoma", 8F);
                this.dataGrid1.ForeColor = System.Drawing.Color.MidnightBlue;
                this.dataGrid1.GridLineColor = System.Drawing.Color.Gainsboro;
                this.dataGrid1.GridLineStyle = System.Windows.Forms.DataGridLineStyle.None;
                this.dataGrid1.HeaderBackColor = System.Drawing.Color.MidnightBlue;
                this.dataGrid1.HeaderFont = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Bold);
                this.dataGrid1.HeaderForeColor = System.Drawing.Color.WhiteSmoke;
                this.dataGrid1.LinkColor = System.Drawing.Color.Teal;
                this.dataGrid1.Location = new System.Drawing.Point(16, 16);
                this.dataGrid1.Name = "dataGrid1";
                this.dataGrid1.ParentRowsBackColor = System.Drawing.Color.Gainsboro;
                this.dataGrid1.ParentRowsForeColor = System.Drawing.Color.MidnightBlue;
                this.dataGrid1.PreferredColumnWidth = 500;
                this.dataGrid1.ReadOnly = true;
                this.dataGrid1.SelectionBackColor = System.Drawing.Color.CadetBlue;
                this.dataGrid1.SelectionForeColor = System.Drawing.Color.WhiteSmoke;
                this.dataGrid1.Size = new System.Drawing.Size(456, 145);
                this.dataGrid1.TabIndex = 0;
                // 
                // addPluginButton
                // 
                this.addPluginButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
                this.addPluginButton.Location = new System.Drawing.Point(480, 24);
                this.addPluginButton.Name = "addPluginButton";
                this.addPluginButton.Size = new System.Drawing.Size(75, 23);
                this.addPluginButton.TabIndex = 1;
                this.addPluginButton.Text = "Add Plugin";
                this.addPluginButton.Click += new System.EventHandler(this.addPluginButton_Click);
                // 
                // remPluginButton
                // 
                this.remPluginButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
                this.remPluginButton.Location = new System.Drawing.Point(480, 64);
                this.remPluginButton.Name = "remPluginButton";
                this.remPluginButton.Size = new System.Drawing.Size(75, 23);
                this.remPluginButton.TabIndex = 2;
                this.remPluginButton.Text = "remove plugin";
                this.remPluginButton.Click += new System.EventHandler(this.remPluginButton_Click);
                // 
                // plugInListBox
                // 
                this.plugInListBox.Location = new System.Drawing.Point(16, 24);
                this.plugInListBox.Name = "plugInListBox";
                this.plugInListBox.Size = new System.Drawing.Size(456, 95);
                this.plugInListBox.TabIndex = 0;
                // 
                // groupBox1
                // 
                this.groupBox1.Controls.Add(this.remPluginButton);
                this.groupBox1.Controls.Add(this.addPluginButton);
                this.groupBox1.Controls.Add(this.dataGrid1);
                this.groupBox1.Location = new System.Drawing.Point(16, 24);
                this.groupBox1.Name = "groupBox1";
                this.groupBox1.Size = new System.Drawing.Size(560, 178);
                this.groupBox1.TabIndex = 0;
                this.groupBox1.TabStop = false;
                this.groupBox1.Text = "Reverse Engineering plugins";
                // 
                // groupBox2
                // 
                this.groupBox2.Controls.Add(this.okButton);
                this.groupBox2.Controls.Add(this.plugInListBox);
                this.groupBox2.Location = new System.Drawing.Point(16, 208);
                this.groupBox2.Name = "groupBox2";
                this.groupBox2.Size = new System.Drawing.Size(560, 136);
                this.groupBox2.TabIndex = 1;
                this.groupBox2.TabStop = false;
                this.groupBox2.Text = "Available Reverse Engineering classes";
                // 
                // revEnggDataSet
                // 
                this.revEnggDataSet.DataSetName = "ReverseEngineers";
                this.revEnggDataSet.Locale = new System.Globalization.CultureInfo("en-US");
                this.revEnggDataSet.Tables.AddRange(new System.Data.DataTable[] {
            this.ReverseEngineeringPlugins});
                // 
                // ReverseEnggPluginForm
                // 
                this.AcceptButton = this.okButton;
                this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                this.ClientSize = new System.Drawing.Size(619, 391);
                this.Controls.Add(this.groupBox2);
                this.Controls.Add(this.groupBox1);
                this.Name = "ReverseEnggPluginForm";
                this.Text = "Reverse Engineers";
                this.Closing += new System.ComponentModel.CancelEventHandler(this.ReverseEnggPluginFormClosing);
                ((System.ComponentModel.ISupportInitialize)(this.ReverseEngineeringPlugins)).EndInit();
                ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
                this.groupBox1.ResumeLayout(false);
                this.groupBox2.ResumeLayout(false);
                ((System.ComponentModel.ISupportInitialize)(this.revEnggDataSet)).EndInit();
                this.ResumeLayout(false);

			}
			#endregion
	

			public IReverseEngineer ReverseEngineer
			{
			
				get
				{
					
					if( this.DialogResult==DialogResult.Cancel)
						return null;
					int index = 0;
					if( this.plugInListBox.SelectedIndex>=0)
					{
						index = this.plugInListBox.SelectedIndex;
						return this.revEngineers[index] as IReverseEngineer;
					}
					return null;				
				}
			}
	
			private void LoadSnapIns()
			{
				// here we read the config file in the same directory.
				DataTable table;
				try
				{
					
					string autoAddPath = dpatoolkit.GlobalSettings.DefaultReverseEngineeringPlugin;
					try
					{
					this.revEnggDataSet.ReadXml(dpatoolkit.GlobalSettings.RevEnggConfigFile);
					}
					catch
					{
					ErrorMessage.Show("Error while reading the configuration file for Reverse Engineering \n plug ins \n Make sure you have write permissions and the file is exists!","Error");	
					}
					
					try{
						silent=true;
                        if (File.Exists(autoAddPath))
                        {
                            this.AddPluginFileEntry(autoAddPath);
                        }
                        else
                        {
                           // MessageBox.Show("Could not auto add default plug-ins! path is :\n" + autoAddPath);
                        }
						silent=false;
					}
					catch(Exception exp)
					{
						ErrorMessage.Show("Encountered the following error : "+exp.ToString());
						
					}
					
					table = this.revEnggDataSet.Tables[PluginTable];
					foreach ( DataRow row in table.Rows)
					{
						this.TryToUseSnapIn((string)row[PathIndex]);
					}
				}
				catch
				{
					ErrorMessage.Show("Error while reading the configuration file for Reverse Engineering \n plug ins \n Make sure you have write permissions and the file is exists!","Error");
				}
			
			}

			private bool TryToUseSnapIn(string path) 
			{
				// Load the asm.
				bool foundSnapIn = false;
				Assembly theSnapInAsm;
				try
				{
					theSnapInAsm = Assembly.LoadFrom(path);
				}
				catch(Exception exp)
				{
					ErrorMessage.Show("Error while reading the assembly:"+path+"\n Exception is :"+exp.ToString() ,"Error");
					return false;
				}

				// Get all types in assembly.
				Type[] theTypes = theSnapInAsm.GetTypes();

				// Get custom attributes for each type, and 
				// see if one of them is [Snappable] 
				for(int i = 0; i < theTypes.Length; i++) 
				{
					//MessageBox.Show(theTypes[i].ToString());
					
					object[] theAtts = theTypes[i].GetCustomAttributes(
						typeof(DesignPatternDefinitions.ReverseEngineerInfo),
						true);
				

					for(int j = 0; j < theAtts.Length; j++) 
					{
						//MessageBox.Show(theAtts[j].ToString());
						if(theAtts[j] is DesignPatternDefinitions.ReverseEngineerInfo) 
						{
							ReverseEngineerInfo lang = theAtts[j] as ReverseEngineerInfo;
							foundSnapIn = true;
							object o = theSnapInAsm.CreateInstance(theTypes[i].FullName);
							IReverseEngineer revEngg;
							revEngg = o as IReverseEngineer;
						
							if(revEngg != null) 
							{
								//MessageBox.Show(revEngg.ToString());
								//if( !this.silent)	
								//MessageBox.Show(this,"The following plug in was found\n Language:"+lang.Language+"\n"+" Provider:"+lang.Provider,
								//"Plugin found",MessageBoxButtons.OK,MessageBoxIcon.Information);
								this.plugInListBox.Items.Add(lang.Language + "," + lang.Provider);
								this.revEngineers.Add(revEngg);
							}																		    
						}					
					}
				}
				return foundSnapIn;

			}

			private void addPluginButton_Click(object sender, System.EventArgs e)
			{
		
				OpenFileDialog myOpenFileDialog = new OpenFileDialog();
				if(myOpenFileDialog.ShowDialog() == DialogResult.OK) 
				{
					//add it  to the table.
					string pathToAsm = myOpenFileDialog.FileName;
					if(this.AddPluginFileEntry(pathToAsm)==false)
						return;
				
					if(TryToUseSnapIn(pathToAsm) == false) 
					{
						ErrorMessage.Show("This is not a valid snap-In or the dll doesnot contain reverse engineering classes.","Error while loading snapIn");
						this.RemovePluginFileEntry(pathToAsm);
						return;
					
					}
					else
						this.plugInListBox.SelectedIndex=0;
				}
			}
			
			private bool AddPluginFileEntry(string fname)
			{
					DataRow row =   this.revEnggDataSet.Tables[PluginTable].NewRow();
					row[0] = fname;
					try
					{
						this.revEnggDataSet.Tables[PluginTable].Rows.Add(row);
					}
					catch
					{
						if(!silent)
						ErrorMessage.Show("This plugin has already been added","error");
						return false;

					}
					return true;
			}
			private void RemovePluginFileEntry(string fname)
			{
				DataTable table = this.revEnggDataSet.Tables[PluginTable];
				DataRow row = table.Rows.Find(fname);
				try{
					table.Rows.Remove(row);
				}
				catch(Exception exp)
				{
					ErrorMessage.Show("Caught exception while removing plugin : "+exp.ToString());
					
				}
				
			}

			private void remPluginButton_Click(object sender, System.EventArgs e)
			{
		
			}

			private void okButton_Click(object sender, System.EventArgs e)
			{
				try
				{
					if(this.plugInListBox.Items.Count<=0)
					{
						MessageBox.Show("No Reverse Engineers were found,\n conider adding the ReverseEngineers.dll available under the sample directory","Info");
					}
					if(this.plugInListBox.SelectedIndex<0)
					{
						//MessageBox.Show("No Reverse Engineers were selected","Info");	
					}
				
					
				}
				catch 
				{
					ErrorMessage.Show("Error! Couldnot write the plugin config file","error");
				}
		
			}
	
			void ReverseEnggPluginFormClosing(object sender, System.ComponentModel.CancelEventArgs e)
			{
				try
				{
					
					foreach ( DataTable table in this.revEnggDataSet.Tables)
						foreach ( DataColumn col in table.Columns)
							col.ColumnMapping = MappingType.Element;
					this.revEnggDataSet.WriteXml(dpatoolkit.GlobalSettings.RevEnggConfigFile);
				}
				catch 
				{
					ErrorMessage.Show("Error! Couldnot write the plugin config file","error");
				}
			}
			
		}
	}